package com.vvv.designpattern.behavioralpattern;


/**
 * @author vvv
 * @date 2023-11-13 12 28
 * discription
 * 迭代器模式，可以让遍历和实现分离开来
 */
public class Interator01 {
    public static void main(String[] args) {
        /**
         * 这里模拟JDK的Interator
         * 在JDK中Collection 接口实现了一个Iterable<T>接口，用来返回某个集合的迭代器
         *Iterable<T>接口中的Iterator<T>接口定义了hasNext和next方法，用来给具体的集合的迭代器来使用的
         */
        MyArrayList<Book> myArrayList = new MyArrayList<>(3);
        myArrayList.add(new Book("A"));
        myArrayList.add(new Book("B"));
        myArrayList.add(new Book("C"));
        Iterator<Book> iterator = myArrayList.iterator();
        while (iterator.hasNext()) {
            Book book = iterator.next();
            System.out.println(book);
        }
    }
}

/**
 * 用来返回某个具体的集合的迭代器
 * @param <T>
 */
interface Iterable<T> {
    Iterator<T> iterator();
}

/**
 * 集合的迭代器
 * @param <E>
 */
interface Iterator<E> {
    // 有没有下一个元素
    boolean hasNext();

    // 返回当前元素并将光标移动到下一个元素
    E next();
}

/**
 * 集合
 * E为集合元素的类型
 */
class MyArrayList<E> implements Iterable<E> {

    private Object[] elementData;

    private int size;

    public MyArrayList(int max) {
        this.elementData = new Object[max];
    }

    public void add(E e) {
        this.elementData[size] = e;
        size ++;
    }

    @Override
    public Iterator<E> iterator() {
        return new Itr();
    }

    private class Itr implements Iterator<E> {
        private int cursor; // 下一个元素的位置
        private int lastRet = -1; // 当前元素的位置
        @Override
        public boolean hasNext() {
            return cursor != size;
        }

        @Override
        public E next() {
            // 当前元素
            int i = cursor;
            if (i > size) {
                throw new RuntimeException("数组越界");
            }
            // 光标移动到下一个
            cursor = i + 1;
            // 返回当前元素
            return (E) elementData[lastRet = i];
        }
    }
}

/**
 * 集合里面的元素
 */
class Book {
    private String name;

    public Book(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    @Override
    public String toString() {
        return "Book{" +
                "name='" + name + '\'' +
                '}';
    }
}



